
export function copyOptArray<T>(opt: T[]): T[] {
    return Array.from(opt);
}

export function copyOptObject<T>(opt: T): T {
    if (opt instanceof Array) {
        return copyOptArray(opt) as any as T;
    }
    const copy: T = {} as any as T;
    for (let attr in opt) {
        if (Object.prototype.hasOwnProperty.call(opt, attr)) {
            copy[attr] = opt[attr];
        }
    }
    return copy;
}

export function copyOpt<T>(opt: T): T {
    if (!opt) {
        return opt as any as T;
    }
    if (typeof opt === "object") {
        return copyOptObject(opt);
    }
    return opt;
}

export function mixedOpt<TA, TB>(optA: TA, optB: TB): TA & TB {
    if (!optA) {
        return optB as TA & TB;
    }
    if (optB instanceof Array) {
        return copyOptArray(optB) as any as TA & TB;
    }
    if (typeof optB === "object") {
        const srcA = copyOpt(optA) as TA & TB;
        for (const attr in optB) {
            if (Object.prototype.hasOwnProperty.call(optB, attr)) {
                srcA[attr] = mixedOpt((optA as any)[attr], optB[attr]);
            }
        }
        return srcA;
    }
    return optB as TA & TB;
}
